package com.haibara.codesubmiteval.aop;

import com.haibara.codesubmiteval.annotation.AuthCheck;
import com.haibara.codesubmiteval.common.ErrorCode;
import com.haibara.codesubmiteval.constant.AuthConstant;
import com.haibara.codesubmiteval.context.UserContext;
import com.haibara.codesubmiteval.exception.BusinessException;
import com.haibara.codesubmiteval.model.entity.User;
import com.haibara.codesubmiteval.service.UserService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * 权限校验 AOP
 */
@Aspect
@Component
@Slf4j
public class AuthInterceptor {

    @Resource
    private UserService userService;

    @Around("@annotation(authCheck)")
    public Object doInterceptor(ProceedingJoinPoint joinPoint, AuthCheck authCheck) throws Throwable {
        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        User loginUser = userService.getLoginUser(request);

        // 将用户信息存入ThreadLocal
        log.info("存储用户信息{}至UserContext", loginUser.getId());
        UserContext.set(loginUser);

        try {
            String mustRole = authCheck.mustRole();
            String userRole = loginUser.getUserRole();
            // 权限校验逻辑
            if (StringUtils.isNotBlank(mustRole)) {
                if (AuthConstant.BAN.equals(userRole)) {
                    throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
                }
                if (AuthConstant.ADMIN.equals(mustRole) && !AuthConstant.ADMIN.equals(userRole)) {
                    // 需要管理员角色，但登录用户不是管理员
                    log.warn("{}无权限，需要权限：{}，用户权限：{}", loginUser.getId(), mustRole, userRole);
                    throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
                }
            }

            // 执行目标方法并获取返回值
            Object result = joinPoint.proceed();
            if (UserContext.hasValue()) {
                log.info("移除UserContext中的用户信息{}", UserContext.get().getId());
            }
            UserContext.remove();
            // 获取方法名
            if (!joinPoint.getSignature().getName().contains("userLogout")) {
                // 如果不是用户注销操作，则进行登录续期
                request.getSession().setMaxInactiveInterval(30 * 24 * 60 * 60);
            }
            return result;
        } finally {
            if (UserContext.hasValue()) {
                log.info("移除UserContext中的用户信息{}", UserContext.get().getId());
            }
            UserContext.remove(); // 确保清除ThreadLocal，防止内存泄漏
        }
    }
}

